<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./assets/global.css">

    <style>
        .preview-container {
            position: relative;
            width: 100%;
            height: 100vh;
        }

        .box-container {
            overflow: hidden;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            /* width: 400px; */
            /* height: 100px; */

            /* transform: scale(2.5); */
        }

        .box-container>div[class*="box"] {
            position: absolute;
            padding: 8px;
            border: 1px solid gray;
            writing-mode: vertical-rl;
            text-orientation: upright;
            white-space: nowrap;
            background-color: #fff;
        }

        #line-canvas {
            position: absolute;
            z-index: -1;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div class="preview-container">
        <div class="box-container">
            <canvas id="line-canvas"></canvas>
        </div>
    </div>
    <script type="module">
        import { recursive, group } from "https://gcore.jsdelivr.net/npm/@3r/tool@1.4.5/lib/common.js"
        import { Maths } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/maths.js";

        // 关系位置逻辑 
        let global = {
            gapLeft: {},
            scale: 1,
            x: 0,
            y: 0
        }

        let config = {
            offsetTop: 120,
            offsetLeft: 40,
            width: 40,
        }

        let orgTree = [
            {
                id: 1,
                name: '公司A',
                children: [
                    {
                        id: 2,
                        name: '公司A1',
                        children: [
                            {
                                id: 3,
                                name: '公司A1-1',
                            }
                        ]
                    },
                    {
                        id: 4,
                        name: '公司A2',
                        children: [
                            {
                                id: 5,
                                name: '公司A2-1',
                            },
                            {
                                id: 6,
                                name: '公司A2-2xxx',
                            }
                        ]
                    }
                ]
            },
            {
                id: 7,
                name: '公司B'
            }
        ]

        let orgList = []

        let boxContainerDom = document.querySelector('.box-container')

        orgList = recursive(orgTree, (item, parent) => {
            item.level = (parent?.level ?? 0) + 1
        })

        orgList.sort((a, b) => b.level - a.level)

        orgList.map(item => {
            if (item.children) {
                item.count = Maths.sum(item.children.map(child => child.count))
            }
            else {
                item.count = 1
            }
        })

        for (let i = 0; i < orgList.length; i++) {
            const item = orgList[i];

            if (!global.gapLeft[item.level]) {
                global.gapLeft[item.level] = 0
            }

            let orgDom = document.createElement('div')

            orgDom.classList.add('box' + item.id)
            orgDom.classList.add('lev' + item.level)
            orgDom.textContent = item.name;


            let offsetTop = config.offsetTop * (item.level - 1)
            let offsetLeft = global.gapLeft[item.level]

            if (item.count > 1) {
                offsetLeft += item.count * config.width / 2 - config.width / 2
                global.gapLeft[item.level] += item.count * config.width - config.offsetLeft
            }


            orgDom.style.top = `${offsetTop}px`
            orgDom.style.left = `${offsetLeft}px`

            global.gapLeft[item.level] += config.offsetLeft

            boxContainerDom.appendChild(orgDom)
        }

        let boxListDom = group(orgList, (item) => item.level).pop().map(item => boxContainerDom.querySelector(`.box${item.id}`))

        let containerWidth = Math.max(...Object.values(global.gapLeft))
        let containerHeight = Math.max(...boxListDom.map(item => item.offsetTop + item.offsetHeight))

        boxContainerDom.style.width = containerWidth + 'px'
        boxContainerDom.style.height = containerHeight + 'px'

        console.log(orgList, boxListDom, containerHeight);

        // 关系线逻辑
        let linkList = []

        for (let i = 0; i < orgList.length; i++) {
            const org = orgList[i];
            if (org.children) {
                org.children.forEach(item => {
                    linkList.push({
                        from: `.box${org.id}`,
                        to: `.box${item.id}`
                    })
                })
            }
        }

        /** @type {HTMLCanvasElement} */
        let canvas = document.querySelector("#line-canvas")
        let ctx = canvas.getContext('2d')
        let width = canvas.clientWidth;
        let height = canvas.clientHeight;
        canvas.width = width;
        canvas.height = height;

        for (const linkItem of linkList) {
            let fromDom = document.querySelector(linkItem.from)
            let toDom = document.querySelector(linkItem.to)

            let fx = fromDom.offsetLeft
            let fy = fromDom.offsetTop
            let fh = fromDom.clientHeight
            let fw = fromDom.clientWidth

            let tx = toDom.offsetLeft
            let ty = toDom.offsetTop
            let th = toDom.clientHeight
            let tw = toDom.clientWidth



            let fxc = fw / 2 + fx;
            let fyc = fh / 2 + fy;

            let txc = tw / 2 + tx;
            let tyc = th / 2 + ty;

            console.log(fromDom, toDom);

            ctx.beginPath()
            ctx.moveTo(fxc, fyc)
            // 经停线
            let cy = ty - (ty - fy - fh) / 2
            let cx = fxc
            ctx.lineTo(cx, cy)
            // 直角
            ctx.lineTo(txc, cy)

            ctx.lineTo(txc, tyc)
            ctx.stroke()
        }


        function updateTransform() {
            boxContainerDom.style.transform = `translate(calc(-50% + ${offsetX}px + ${global.x}px),calc(-50% + ${offsetY}px + ${global.y}px)) scale(${global.scale})`
        }


        // 缩放逻辑
        document.addEventListener("wheel", (event) => {
            global.scale += .05 * Math.sign(event.wheelDeltaY)
            updateTransform()
        });

        // 移动逻辑
        let isStartMove = false
        let startX = 0;
        let startY = 0;
        let offsetX = 0;
        let offsetY = 0;

        document.addEventListener("mousedown", (event) => {
            isStartMove = true
            startX = event.x;
            startY = event.y
        })

        document.addEventListener("mousemove", (event) => {
            if (event.ctrlKey && isStartMove) {
                offsetX = event.x - startX
                offsetY = event.y - startY
                updateTransform()
            }
        })

        document.addEventListener("mouseup", (event) => {
            isStartMove = false;
            global.x += offsetX;
            global.y += offsetY;
            offsetX = 0;
            offsetY = 0;
        })

    </script>

</body>

</html>